﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Resources;
using System.Drawing;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

using TagLib;
using TagLib.Id3v1;

namespace AMPLibrary.Media
{
    [Serializable]
    public class Tag : ISerializable
    {
        private string MediaPath
        {
            get;
            set;
        }

        public string Title
        {
            get;
            set;
        }

        public string AlbumArtist
        {
            get;
            set;
        }

        public string Album
        {
            get;
            set;
        }

        public string Year
        {
            get;
            set;
        }

        public string Comment
        {
            get;
            set;
        }

        public int Track
        {
            get;
            set;
        }

        public string Genre
        {
            get;
            set;
        }

        public uint BeatsPerMinute
        {
            get;
            set;
        }

        public string Lyrics
        {
            get;
            set;
        }

        public string[] Composers
        {
            get;
            set;
        }

        public string Conductor
        {
            get;
            set;
        }

        public string[] Performers
        {
            get;
            set;
        }

        public int Rating
        {
            get;
            set;
        }

        public DateTime DateAdded
        {
            get;
            set;
        }

        public DateTime DateUpdated
        {
            get;
            set;
        }

        public Tag()
        {
            Title = string.Empty;
            AlbumArtist = "Unknown Artist";
            Album = string.Empty;
            Conductor = string.Empty;
            Year = string.Empty;
            Comment = string.Empty;
            Track = 0;
            Genre = "Unknown Genre";
            Year = string.Empty;
            DateAdded = DateTime.MinValue;
            DateUpdated = DateTime.MinValue;
        }

        public Tag(TagLib.File file, string path)
        {
            this.MediaPath = path;
            TagLib.Id3v2.Tag id3v2 = (TagLib.Id3v2.Tag)file.GetTag(TagLib.TagTypes.Id3v2);

            if (id3v2 == null)
            {
                this.Title = Path.GetFileName(path);
                return;
            }

            // Title
            if (id3v2.Title != null)
            {
                if(id3v2.Title != string.Empty)
                    this.Title = id3v2.Title;
                else
                    this.Title = Path.GetFileName(path);
            }
            else
                Title = Path.GetFileName(path);

            // Album
            if (id3v2.Album != null)
                this.Album = id3v2.Album;
            else
                this.Album = "Unknown Album";
            
            // album artists
            if (id3v2.AlbumArtists.Length > 0)
                this.AlbumArtist = id3v2.AlbumArtists[0];
            else
                this.AlbumArtist = "Unknown Artist";

            // composers
            if (id3v2.Composers.Length > 0)
                this.Composers = id3v2.Composers;
            else
                this.Composers = new string[] { "Unknown Artist" };

            // conductors
            if (id3v2.Conductor != null)
                this.Conductor = id3v2.Conductor;
            else
                this.Conductor = "Unknown Conductor";

            // Genres
            if (id3v2.Genres.Length > 0)
                this.Genre = id3v2.Genres[0];
            else
                this.Genre = "Unknown Genre";

            // comments
            if (id3v2.Comment != string.Empty)
                this.Comment = id3v2.Comment;
            else
                this.Comment = string.Empty;

            // Track number
            if (id3v2.Track.ToString() != string.Empty)
                this.Track = Convert.ToInt32(id3v2.Track);
            else
                this.Track = 0;

            // BPM
            this.BeatsPerMinute = id3v2.BeatsPerMinute;

            // Performers
            if (id3v2.Performers.Length > 0)
                this.Performers = id3v2.Performers;
            else
                this.Performers = new string[] { "Unknown Performer" };

            // Lyrics
            if (id3v2.Lyrics != null)
                this.Lyrics = id3v2.Lyrics;
            else
                Lyrics = string.Empty;

            // year
            if (id3v2.Year.ToString() != string.Empty)
                this.Year = id3v2.Year.ToString();
            else
                this.Year = "Unknown Year";

            if(this.Year == "0")
                this.Year = "Unknown Year";

            // date added
            this.DateAdded = DateTime.Now;
            this.DateUpdated = DateTime.Now;
        }

        /// <summary>
        /// Method, saves the information to the media file on the hard drive
        /// </summary>
        public void WriteTagToDisk()
        {
            TagLib.File file = TagLib.File.Create(MediaPath);

            if (file == null)
                return;

            // artist tag editor
            file.Tag.AlbumArtists = new string[] { this.AlbumArtist };

            // album tag editor
            file.Tag.Album = this.Album;
            file.Tag.Genres = new string[] { this.Genre };
            file.Tag.Composers = this.Composers;
            file.Tag.Conductor = this.Conductor;

            // song
            file.Tag.Title = this.Title;            
            file.Tag.Track = Convert.ToUInt32(this.Track);

            uint year = 0;
            if(UInt32.TryParse(this.Year, out year))
                file.Tag.Year = year;

            // save
            file.Save();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="info"></param>
        /// <param name="ctxt"></param>
        public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
        {
            info.AddValue("MediaPath", this.MediaPath);
            info.AddValue("Title", this.Title);
            info.AddValue("Album", this.Album);
            info.AddValue("Conductor", this.Conductor);
            info.AddValue("Composers", this.Composers);
            info.AddValue("AlbumArtist", this.AlbumArtist);
            info.AddValue("Genre", this.Genre);
            info.AddValue("Comment", this.Comment);
            info.AddValue("Track", this.Track);
            info.AddValue("Year", this.Year);
            info.AddValue("DateAdded", this.DateAdded);
            info.AddValue("DateUpdated", this.DateUpdated);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="info"></param>
        /// <param name="ctxt"></param>
        public Tag(SerializationInfo info, StreamingContext ctxt)
        {
            Title = string.Empty;
            AlbumArtist = "Unknown Artist";
            Album = string.Empty;
            Conductor = string.Empty;
            Year = string.Empty;
            Comment = string.Empty;
            Track = 0;
            Genre = "Unknown Genre";
            Year = string.Empty;
            DateAdded = DateTime.MinValue;
            DateUpdated = DateTime.MinValue;

            try
            {
                this.MediaPath = (string)info.GetValue("MediaPath", typeof(string));
            }
            catch
            {
            }
            
            try
            {
                this.Title = (string)info.GetValue("Title", typeof(string));
            }
            catch
            {
            }
            
            try
            {
                this.Album = (string)info.GetValue("Album", typeof(string));
            }
            catch
            {
            }
            
            try
            {
                this.Conductor = (string)info.GetValue("Conductor", typeof(string));
            }
            catch
            {
            }
            
            try
            {
                this.Composers = (string[])info.GetValue("Composers", typeof(string[]));
            }
            catch
            {
            }
            
            try
            {
                this.AlbumArtist = (string)info.GetValue("AlbumArtist", typeof(string));
            }
            catch
            {
            }
            
            try
            {
                this.Genre = (string)info.GetValue("Genre", typeof(string));
            }
            catch
            {
            }
            
            try
            {
                this.Comment = (string)info.GetValue("Comment", typeof(string));
            }
            catch
            {
            }
            
            try
            {
                this.Year = (string)info.GetValue("Year", typeof(string));
            }
            catch
            {
            }
            
            try
            {
                this.Track = (int)info.GetValue("Track", typeof(int));
            }
            catch
            {
            }
            
            try
            {
                this.DateAdded = (DateTime)info.GetValue("DateAdded", typeof(DateTime));
            }
            catch
            {
            }
            
            try
            {
                this.DateUpdated = (DateTime)info.GetValue("DateUpdated", typeof(DateTime));
            }
            catch
            {
            }
        }
    }
}
